package com.quick.system.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import com.quick.common.annotation.DataScope;
import com.quick.common.annotation.DataScopeByGetInfo;
import com.quick.common.constants.Constants;
import com.quick.common.constants.UserConstants;
import com.quick.common.core.domain.BaseEntity;
import com.quick.common.core.domain.LoginUser;
import com.quick.common.core.domain.Select;
import com.quick.common.exception.ServiceException;

import com.quick.common.utils.DateUtils;
import com.quick.common.utils.SecurityUtils;
import com.quick.common.utils.ServletUtils;
import com.quick.common.utils.ip.IpUtils;
import com.quick.common.utils.spring.SpringUtils;
import com.quick.system.domain.*;
import com.quick.system.mapper.*;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.quick.system.service.SysUserService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

/**
 * 用户信息Service业务层处理
 *
 * @Author: 吃素不吃肉
 * @Date: Tue Jul 25 14:14:44 CST 2023
 */
@Service
public class SysUserServiceImpl implements SysUserService {
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysUserPostMapper sysUserPostMapper;
    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;
    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private SysPostMapper sysPostMapper;

    /**
     * 查询用户信息
     *
     * @param userId 用户信息主键
     * @return 用户信息
     */
    @Override
    @DataScopeByGetInfo(field = "userId", type = DataScopeByGetInfo.USER)
    public SysUser selectSysUserByUserId(Long userId) {
        return sysUserMapper.selectSysUserByUserId(userId);
    }

    /**
     * 查询用户信息
     *
     * @param userName 用户账号
     * @return 用户信息
     */
    @Override
    public SysUser selectSysUserByUserName(String userName) {
        return sysUserMapper.selectSysUserByUserName(userName);
    }

    /**
     * 查询用户信息列表
     *
     * @param user 用户信息
     * @return 用户信息
     */
    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<SysUser> selectSysUserList(SysUser user) {
        return sysUserMapper.selectSysUserList(user);
    }

    /**
     * 根据条件分页查询已分配用户角色列表
     *
     * @param user 用户信息
     * @return 用户信息集合信息
     */
    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<SysUser> selectAllocatedList(SysUser user) {
        return sysUserMapper.selectAllocatedList(user);
    }

    /**
     * 根据条件分页查询未分配用户角色列表
     *
     * @param user 用户信息
     * @return 用户信息集合信息
     */
    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<SysUser> selectUnAllocatedList(SysUser user) {
        return sysUserMapper.selectUnAllocatedList(user);
    }

    /**
     * 新增用户信息
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertSysUser(SysUser user) {
        checkUserAllowed(user);
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (Objects.nonNull(sysUserMapper.selectSysUserByUserName(user.getUserName()))) {
            throw new ServiceException("用户名已存在！");
        }
        user.setCreateTime(new Date());
        user.setCreateBy(loginUser.getUsername());
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        int row = sysUserMapper.insertSysUser(user);
        insertUserPost(user);
        insertUserRole(user);
        return row;
    }

    /**
     * 新增用户岗位信息
     *
     * @param user 用户
     */
    public void insertUserPost(SysUser user) {
        Long userId = user.getUserId();
        // 删除用户与岗位关联
        sysUserPostMapper.deleteSysUserPostByUserId(user.getUserId());
        List<?> postIds = (List<?>) user.getParams().get("postIds");
        if (postIds != null && postIds.size() > 0) {
            // 新增用户与岗位管理
            List<SysUserPost> list = new ArrayList<>();
            for (Object postId : postIds) {
                SysUserPost up = new SysUserPost();
                up.setUserId(userId);
                up.setPostId(Long.valueOf(postId.toString()));
                list.add(up);
            }
            if (!CollectionUtils.isEmpty(list)) {
                sysUserPostMapper.batchUserPost(list);
            }
        }
    }

    /**
     * 新增用户角色信息
     *
     * @param user 用户
     */
    public void insertUserRole(SysUser user) {
        Long userId = user.getUserId();
        List<?> roleIds = (List<?>) user.getParams().get("roleIds");
        insertUserRole(userId, roleIds);
    }

    /**
     * 新增用户角色信息
     *
     * @param userId  用户id
     * @param roleIds 角色id集合
     */
    public void insertUserRole(Long userId, List<?> roleIds) {
        // 删除用户与角色关联
        sysUserRoleMapper.deleteSysUserRoleByUserId(userId);
        if (roleIds != null && roleIds.size() > 0) {
            // 新增用户与角色管理
            List<SysUserRole> list = new ArrayList<>();
            for (Object roleId : roleIds) {
                SysUserRole ur = new SysUserRole();
                ur.setUserId(userId);
                ur.setRoleId(Long.valueOf(roleId.toString()));
                list.add(ur);
            }
            if (!CollectionUtils.isEmpty(list)) {
                sysUserRoleMapper.batchUserRole(list);
            }
        }
    }

    /**
     * 修改用户信息
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @DataScopeByGetInfo(field = "userId", type = DataScopeByGetInfo.USER)
    public int updateSysUser(SysUser user) {
        checkUserAllowed(user);
        SpringUtils.getBean(this.getClass()).checkUserDataScope(user.getUserId());
        user.setUpdateTime(new Date());
        // 新增用户与角色管理
        insertUserRole(user);
        // 新增用户与岗位管理
        insertUserPost(user);
        user.setUpdateBy(SecurityUtils.getLoginUser().getUsername());
        user.setPassword(null);
        return sysUserMapper.updateSysUser(user);
    }

    /**
     * 批量删除用户信息
     *
     * @param userIds 需要删除的用户信息主键
     * @return 结果
     */
    @Override
    @DataScopeByGetInfo(field = "userIds", type = DataScopeByGetInfo.USER)
    public int deleteSysUserByUserIds(Long[] userIds) {
        if (ArrayUtils.contains(userIds, SecurityUtils.getLoginUser().getUserId())) {
            throw new ServiceException("不允许删除当前登录用户！");
        }
        return sysUserMapper.deleteSysUserByUserIds(userIds);
    }

    /**
     * 重置密码
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    @DataScopeByGetInfo(field = "userId", type = DataScopeByGetInfo.USER)
    public int resetPwd(SysUser user) {
        checkUserAllowed(user);
        SpringUtils.getBean(this.getClass()).checkUserDataScope(user.getUserId());
        SysUser userUpdate = new SysUser();
        userUpdate.setUserId(user.getUserId());
        userUpdate.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        userUpdate.setUpdateBy(SecurityUtils.getLoginUser().getUsername());
        return sysUserMapper.updateSysUser(userUpdate);
    }

    /**
     * 修改用户状态
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    @DataScopeByGetInfo(field = "userId", type = DataScopeByGetInfo.USER)
    public int changeStatus(SysUser user) {
        checkAdmin(user);
        checkUserAllowed(user);
        SpringUtils.getBean(this.getClass()).checkUserDataScope(user.getUserId());
        SysUser userUpdate = new SysUser();
        userUpdate.setUpdateBy(SecurityUtils.getLoginUser().getUsername());
        userUpdate.setUserId(user.getUserId());
        userUpdate.setStatus(user.getStatus());
        return sysUserMapper.updateSysUser(userUpdate);
    }


    /**
     * 校验用户是否允许操作
     *
     * @param user 用户信息
     */

    public void checkUserAllowed(SysUser user) {
        Long userId = user.getUserId();
        //手机号对应的用户与当前操作用户不一致则提示手机号重复
        SysUser sysUser = sysUserMapper.selectSysUserByPhoneNumber(user.getPhoneNumber());
        if (Objects.nonNull(sysUser)
                && !sysUser.getUserId().equals(userId)) {
            throw new ServiceException("手机号已存在！");
        }
    }

    /**
     * 校验用户是否允许操作
     *
     * @param user 用户信息
     */
    public void checkAdmin(SysUser user) {
        //操作用户id
        Long userId = user.getUserId();
        if (UserConstants.ADMIN_USER_ID.equals(userId)) {
            throw new ServiceException("不允许操作超级管理员用户！");
        }
    }

    /**
     * 检查用户访问权限
     *
     * @param userId 用户id
     */
    @Override
    @DataScope(userAlias = "u")
    public void checkUserDataScope(Long userId) {
        List<Long> ids = sysUserMapper.checkUserDataScope(new BaseEntity());
        if (CollectionUtils.isEmpty(ids) || !ids.contains(userId)) {
            throw new ServiceException("没有权限访问用户数据！");
        }
    }

    /**
     * 检查用户访问权限
     *
     * @param userIds 用户ids
     */

    @Override
    @DataScope(userAlias = "u")
    public void checkUserDataScope(Long[] userIds) {
        List<Long> ids = sysUserMapper.checkUserDataScope(new BaseEntity());
        if (CollectionUtils.isEmpty(ids) || !new HashSet<>(ids).containsAll(Arrays.asList(userIds))) {
            throw new ServiceException("没有权限访问用户数据！");
        }
    }

    /**
     * 根据用户编号获取授权角色
     *
     * @param userId 用户id
     * @return 授权角色信息
     */
    @Override
    public Map<String, Object> authRole(Long userId) {
        SysUser user = sysUserMapper.selectSysUserByUserId(userId);
        List<SysRole> userRoles = sysRoleMapper.selectSysRoleByUserId(userId);
        List<SysRole> roles = sysRoleMapper.selectSysRoleList(new SysRole());
        for (SysRole role : roles) {
            for (SysRole userRole : userRoles) {
                if (role.getRoleId().longValue() == userRole.getRoleId().longValue()) {
                    Map<String, Object> params = new HashMap<>(1);
                    params.put("flag", true);
                    role.setParams(params);
                    break;
                }
            }
        }
        Map<String, Object> data = new HashMap<>(2);
        data.put("user", user);
        data.put("roles", UserConstants.ADMIN_USER_ID.equals(userId) ? roles : roles.stream().filter(r -> !UserConstants.ADMIN_ROLE.equals(r.getRoleKey())).collect(Collectors.toList()));
        return data;
    }

    /**
     * 用户授权角色
     *
     * @param userId  用户ID
     * @param roleIds 角色组
     */
    @Override
    public void insertUserAuth(Long userId, Long[] roleIds) {
        insertUserRole(userId, Arrays.asList(roleIds));
    }

    /**
     * 更新记录登录信息
     *
     * @param userId 用户Id
     */
    @Override
    public void updateRecordLoginInfo(Long userId) {
        SysUser sysUser = new SysUser();
        sysUser.setUserId(userId);
        sysUser.setLoginIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
        sysUser.setLoginDate(DateUtils.getNowDate());
        sysUserMapper.updateSysUser(sysUser);
    }


    /**
     * 获取职位和角色列表
     *
     * @return 职位和角色列表
     */
    @Override
    public Map<String, Object> getPostAndRole() {
        Map<String, Object> data = new HashMap<>(2);
        SysRole sysRoleQuery = new SysRole();
        sysRoleQuery.setStatus(Constants.STATUS_ENABLE);
        List<SysRole> sysRoles = sysRoleMapper.selectSysRoleList(sysRoleQuery);
        List<Select> selectRoles = Select.getSelect();
        for (SysRole sysRole : sysRoles) {
            selectRoles.add(new Select(sysRole.getRoleName(), sysRole.getRoleId()));
        }
        SysPost sysPostQuery = new SysPost();
        sysPostQuery.setStatus(Constants.STATUS_ENABLE);
        List<SysPost> sysPosts = sysPostMapper.selectSysPostList(new SysPost());
        List<Select> selectPosts = Select.getSelect();
        for (SysPost sysPost : sysPosts) {
            selectPosts.add(new Select(sysPost.getPostName(), sysPost.getPostId()));
        }
        data.put("roles", selectRoles);
        data.put("posts", selectPosts);
        return data;
    }

    /**
     * 获取用户信息详细信息
     *
     * @param userId 用户id
     * @return 用户信息详细信息
     */
    @Override
    @DataScopeByGetInfo(field = "userId", type = DataScopeByGetInfo.USER)
    public SysUser getInfo(Long userId) {
        Map<String, Object> params = new HashMap<>(3);
        params.put("postIds", sysPostMapper.selectSysPostByUserId(userId).stream().map(SysPost::getPostId).collect(Collectors.toList()));
        params.put("roleIds", sysRoleMapper.selectSysRoleByUserId(userId).stream().map(SysRole::getRoleId).collect(Collectors.toList()));
        SysUser user = sysUserMapper.selectSysUserByUserId(userId);
        user.setParams(params);
        return user;
    }
}
